﻿using System;
using System.Collections.Generic;
using Engine;
using Game;
using TemplatesDatabase;
namespace Mekiasm
{
    public class PlantSystem
    {
        public class PlantItem
        {
            public int RemainTimes = 0;//本次周期生长剩余时间
            public int DurationTimes = 0;//一个周期的时间
            public Point3 point;//生长地点
            public bool Active;//是否激活
            public int Value;//用于寻找MekBlock的Item
            public int GrowState;//第几个生长周期
            public bool Remove
            {
                get;
                set;
            }
            public Action<PlantItem, int, bool, int> GrowStateChange;
            public Func<int, bool> Check;
            public PlantItem(int x, int y, int z, int Value, int DurationTimes, Action<PlantItem, int, bool, int> GrowStateChange = null, Func<int, bool> Check = null)
            {
                point = new Point3(x, y, z);
                this.Value = Value;
                this.RemainTimes = this.DurationTimes = DurationTimes;
                this.GrowStateChange = GrowStateChange;
                if (Check == null)
                {
                    this.Check = (v) => { return v == ILibrary.setExtraData(v, this.GrowState); };
                }
                else this.Check = Check;
            }
        }

        public static void OnChunkInitialized(TerrainChunk chunk)
        {
            for (int i = 0; i < PlantItems.Count; i++)
            {
                PlantItem plantItem = PlantItems[i];
                Point2 point2 = Terrain.ToChunk(plantItem.point.X, plantItem.point.Z);
                if (point2 == chunk.Coords) plantItem.Active = true;

            }
        }

        public static void OnChunkDiscarding(TerrainChunk chunk)
        {
            for (int i = 0; i < PlantItems.Count; i++)
            {
                PlantItem plantItem = PlantItems[i];
                Point2 point2 = Terrain.ToChunk(plantItem.point.X, plantItem.point.Z);
                if (point2 == chunk.Coords) plantItem.Active = false;

            }
        }
        public static List<PlantItem> PlantItems = new List<PlantItem>();

        public static MekPlantsBlock block;

        public static void Add(PlantItem plantItem)
        {
            PlantItem plantItem1 = PlantItems.Find(p => p.point == plantItem.point);
            if (plantItem1 == null)
            {
                plantItem.Active = true;
                PlantItems.Add(plantItem);
            }
            else
            {
                PlantItems.Remove(plantItem1);
                plantItem.Active = true;
                PlantItems.Add(plantItem);
            }
        }
        public static void Remove(Point3 x)
        {
            var t = PlantItems.Find(p => p.point == x);
            if (t != null) PlantItems.Remove(t);
        }
        public static void Load(ValuesDictionary pairs)
        {
            block = BlocksManager.Blocks[MekPlantsBlock.Index] as MekPlantsBlock;
            foreach (ValuesDictionary pairs1 in pairs.Values)
            {
                int v = pairs1.GetValue<int>("Value");
                Point3 point = pairs1.GetValue<Point3>("point");
                PlantItem plantItem = block.GetPlantItem(v, point.X, point.Y, point.Z);
                plantItem.GrowState = pairs1.GetValue<int>("GrowState");
                plantItem.point = point;
                plantItem.RemainTimes = pairs1.GetValue<int>("RemainTimes");
                PlantItems.Add(plantItem);
            }
        }

        public static ValuesDictionary Save()
        {
            ValuesDictionary pairs = new ValuesDictionary();
            for (int i = 0; i < PlantItems.Count; i++)
            {
                ValuesDictionary keys = new ValuesDictionary();
                keys.SetValue("RemainTimes", PlantItems[i].RemainTimes);
                keys.SetValue("GrowState", PlantItems[i].GrowState);
                keys.SetValue("point", PlantItems[i].point);
                keys.SetValue("Value", PlantItems[i].Value);
                pairs.SetValue(i.ToString(), keys);
            }
            return pairs;
        }

        public static void Update(float dt)
        {
            for (int i = 0; i < PlantItems.Count; i++)
            {
                PlantItem plantItem = PlantItems[i];
                if (!plantItem.Active) continue;
                int light = ILibrary.SubsystemTerrain.Terrain.GetCellLightFast(plantItem.point.X, plantItem.point.Y, plantItem.point.Z);
                if (light < 10) continue;
                int v = ILibrary.SubsystemTerrain.Terrain.GetCellValueFast(plantItem.point.X, plantItem.point.Y - 1, plantItem.point.Z);
                int vv = ILibrary.SubsystemTerrain.Terrain.GetCellValueFast(plantItem.point.X, plantItem.point.Y, plantItem.point.Z);
                int ID = Terrain.ExtractContents(v);
                int data = Terrain.ExtractData(v);
                bool hydration = SoilBlock.GetHydration(data);
                int Nitrogen = SoilBlock.GetNitrogen(data);

                if (ILibrary.SubsystemTime.PeriodicGameTimeEvent(1.0, 0.0))
                {
                    plantItem.RemainTimes -= MathUtils.Max(1, Nitrogen);
                }
                if (plantItem.RemainTimes <= 0)
                {
                    if (!plantItem.Check(vv))
                    {
                        PlantItems.RemoveAt(i);
                        continue;
                    }
                    plantItem.GrowState += 1;
                    plantItem.RemainTimes = plantItem.DurationTimes;
                    plantItem.GrowStateChange?.Invoke(plantItem, ID, hydration, Nitrogen);
                    if (plantItem.Remove) PlantItems.RemoveAt(i);
                }
            }
        }
        public static void Dispose()
        {
            PlantItems.Clear();
        }
    }
}
